package main;

import input.ParserArchivo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import states.EstadoAccion;
import states.EstadoEntrada;

public class Turing {
	
	private static List<Character> tape;
	private static Integer initialIndex, finalIndex;
	private static Integer actualIndex;
	
	public static void main(String[] args) throws IOException {
		Integer ind;
		int inputInt;
		char inputChar;
		boolean fin = false;
		ParserArchivo parser;

		actualIndex=initialIndex=finalIndex=0;
		tape = new ArrayList<Character>();
		tape.add('0');
		
		if (args.length < 1) {
			System.out.println("ERROR: Se debe ingresar por linea de " +
					"comandos el archivo mt para cargar.");
			return;
		}

		String filename = args[0];

		try {
			parser = new ParserArchivo(filename);
		} catch (Exception e) {
			System.err.println("ERROR: Error al leer archivo de entrada.");
			System.err.println("PROBLEMA: " + e.getMessage());
			return;
		}

		Map<EstadoEntrada,EstadoAccion> transiciones = parser.getTransiciones();
		String actualState = parser.getInitialState();
					
		while(true){
			inputInt = System.in.read();
			
			if (inputInt == 13 || inputInt == 10) {
				break;
			}
			inputChar=(char) inputInt;
			if (inputChar!='0' && inputChar!='1' && inputChar!='2'){
				System.out.println("ERROR: Los unicos caracteres validos son 0, 1 y 2.");
				System.out.println("FIN DE LA APLICACION");
				return;
			}
			WriteTape(inputChar);
			actualIndex++;
		}
		actualIndex=0;

		while(!fin){
			inputChar=ReadTape();
			EstadoEntrada estadoEntradaAux = new EstadoEntrada(actualState,inputChar);
			EstadoAccion estadoAccionAux = transiciones.get(estadoEntradaAux);
			if (estadoAccionAux!=null){
				actualState=estadoAccionAux.getEstado();
				//System.out.println("CAMBIE EL ESATDO ACTUAL A "+actualState);
				switch(estadoAccionAux.getAccion()){
				case '<':
					MoveTapeLeft();
					break;
				case '>':
					MoveTapeRight();
					break;
				default:
					WriteTape(estadoAccionAux.getAccion());
					break;
				}
			}
			else{
				fin=true;
			}
		}

		for (ind=initialIndex;ind<=finalIndex;ind++){
			PrintTape(ind);
		}
		System.out.println("");
		System.out.flush();
		return;
	}
	
	private static int mapToList(int ind){
		if (ind>=0)
			return 2*ind;
		else
			return -1*ind;
	}
	
	private static void WriteTape(char value){
		int listIndex=mapToList(actualIndex);
		CheckTapeAndExpand();
		tape.set(listIndex, value);
		
	}
	
	private static void CheckTapeAndExpand(){
		int listIndex=mapToList(actualIndex);
		if (tape.size()<=listIndex){
			tape.add('0');
			tape.add('0');
		}
	}
	
	private static char ReadTape(){
		int listIndex=mapToList(actualIndex);
		return tape.get(listIndex);
	}
	
	private static void MoveTapeLeft(){
		actualIndex--;
		if (actualIndex<initialIndex)
			initialIndex=actualIndex;
		
		CheckTapeAndExpand();
	}
	
	private static void MoveTapeRight(){
		actualIndex++;
		if (actualIndex>finalIndex)
			finalIndex=actualIndex;
		
		CheckTapeAndExpand();
	}
	
	private static void PrintTape(int ind){
		int listIndex=mapToList(ind);
		System.out.print(tape.get(listIndex));
	}
}
